package tcpserver

import (
	"net"
	"sync"
	"util/log"
)

const (
	SENDPKGLEN = 1024 * 2 //2k
	RECVPKGLEN = 1024 * 8 //8k
)

type datapkg struct {
	size int
	data []byte
}

//连接回调
type Connecter interface {
	OnConnect(index int, serial int, addr net.Addr)
	OnDisconnect(index int, serial int)
}

//数据回调
type Reader interface {
	Recv(index int, serial int, data []byte, size int)
}

//每个socket连接
type Conn struct {
	active   bool
	index    int
	serial   int
	conn     net.Conn
	bquit    chan bool
	incoming chan datapkg
	lock     sync.Mutex
}

func (conn *Conn) address() net.Addr {
	return conn.conn.RemoteAddr()
}

//判断两个连接是否相等
func (conn *Conn) Equal(other Conn) bool {
	if conn.serial == other.serial {
		if conn.conn == other.conn {
			return true
		}
	}

	return false
}

//从socket读数据
func (conn *Conn) Read(pkg *datapkg) bool {
	bytelen, err := conn.conn.Read(pkg.data)
	if err != nil {
		return false
	}
	pkg.size = bytelen
	return true
}

//写数据
func (conn *Conn) Send(data []byte, size int) {
	pkg := datapkg{size, data}
	conn.incoming <- pkg
}

//读进程(每个socket一个)
func clientReader(server *TcpServer, conn *Conn) {
	pkg := &datapkg{0, make([]byte, RECVPKGLEN)}

	for conn.Read(pkg) {
		reader, ok := server.callee.(Reader)
		if ok {
			reader.Recv(conn.index, conn.serial, pkg.data, pkg.size)
			if server.debug {
				log.LogDebug("recv:", conn.index, conn.serial, pkg.size, " bytes")
			}
		}
	}

	//socket已经断开,通知发送进程结束循环
	connecter, ok := server.callee.(Connecter)
	if ok {
		connecter.OnDisconnect(conn.index, conn.serial)
	}

	conn.bquit <- true
}

//写进程(每个socket一个)
func clientSender(server *TcpServer, conn *Conn) {
loop:
	for {
		select {
		case buffer := <-conn.incoming:
			n, err := conn.conn.Write(buffer.data[0:buffer.size])
			if err != nil {
				log.LogError("socket send err:", err)
			}

			if server.debug {
				log.LogDebug("send:", conn.index, conn.serial, n, " bytes")
			}

		case <-conn.bquit:
			server.closeConn(conn.index)
			break loop
		}
	}
}

//开始连接
func connStart(server *TcpServer, conn *Conn) {
	go clientReader(server, conn)
	go clientSender(server, conn)
}

//收到新的连接
func connHandler(server *TcpServer, conn net.Conn) {
	idx := -1
	if idx = server.addConn(conn); idx == -1 {
		log.LogError("socket pool is full")
		conn.Close()
		return
	}
	newconn := server.lockConn(idx)
	if newconn == nil {
		log.LogError("conn not found")
		conn.Close()
	}
	defer server.unlockConn(idx)
	connecter, ok := server.callee.(Connecter)
	if ok {
		connecter.OnConnect(newconn.index, newconn.serial, conn.RemoteAddr())
	}
	connStart(server, newconn)

}
